library(tidyverse)
library(caret)
Data


Numbers divided by quartiles in order to determine the profiles of rankings that are slow and fast. The profiles are divided in four equal parts considering the number of alternatives and one quarter is taking as fast and the other considered as slow.
Storing counts in `nn`, as `n` already present in input
ℹ Use `name = "new_name"` to pick a new name.
Using alpha for a discrete variable is not advised.
# For the reggresion problem
# fitControl <- trainControl(
# method = "repeatedcv",
# number = 5,
# repeats = 2)
fitControl <- trainControl(
method = "repeatedcv",
number = 5,
repeats = 2,
classProbs = TRUE,
summaryFunction = prSummary)
Predicting execution time for profiles of a fixed size
Joining, by = c("n", "m", "id")
# Fit control para
fitControl <- trainControl(
method = "repeatedcv",
number = 5,
repeats = 2,
classProbs = TRUE,
summaryFunction = prSummary)
Training 25%-75%
# Da muy malos resultados porque está desbalanceado
# # Para n = 10
# totrain <- data_quartiles %>%
# filter(n==10) %>%
# mutate(quartile = fct_collapse(quartile, fast = c("q1"), slow = c("q2","q3","q4"))) %>%
# select(starts_with("mu"), quartile)
# set.seed(123)
# trainIndex <- createDataPartition(totrain$quartile, p = .8,
# list = FALSE,
# times = 1)
# dataTrain <- totrain[ trainIndex,]
# dataTest <- totrain[-trainIndex,]
# set.seed(123)
# mclas_rf_10 <- train(
# quartile ~., data = dataTrain,
# method = "rf",
# tuneLength = 3,
# trControl = fitControl,
# metric = "AUC"
# )
# mclas_rf_10
library(ROSE)
Para n = 10 con los datos normalizados
Y en test:
pred <- predict(rf_10_rose_norm, dataTest)
postResample(pred = pred, obs = dataTest$quartile)
confusionMatrix(data = pred, reference = dataTest$quartile, mode = "prec_recall")
Y sin normalizar:
fitControl <- trainControl(
method = "repeatedcv",
number = 5,
repeats = 2,
classProbs = TRUE,
summaryFunction = prSummary,
sampling = "up")
Error in trainControl(method = "repeatedcv", number = 5, repeats = 2, :
no se pudo encontrar la función "trainControl"
rf_10_rose
Random Forest
2240 samples
16 predictor
2 classes: 'fast', 'slow'
No pre-processing
Resampling: Cross-Validated (5 fold, repeated 2 times)
Summary of sample sizes: 1792, 1792, 1792, 1792, 1792, 1792, ...
Resampling results across tuning parameters:
mtry AUC Precision Recall F
2 0.7875077 0.7439379 0.7243243 0.7336813
9 0.7803522 0.7403700 0.7391892 0.7394959
16 0.7768513 0.7310205 0.7436937 0.7371480
AUC was used to select the optimal model using the largest value.
The final value used for the model was mtry = 2.
confusionMatrix(data = pred, reference = (dataTest %>% filter(quartile == "fast"))$quartile, mode = "prec_recall")
Confusion Matrix and Statistics
Reference
Prediction fast slow
fast 125 0
slow 15 0
Accuracy : 0.8929
95% CI : (0.8294, 0.9388)
No Information Rate : 1
P-Value [Acc > NIR] : 1.0000000
Kappa : 0
Mcnemar's Test P-Value : 0.0003006
Precision : 1.0000
Recall : 0.8929
F1 : 0.9434
Prevalence : 1.0000
Detection Rate : 0.8929
Detection Prevalence : 0.8929
Balanced Accuracy : NA
'Positive' Class : fast
rose_train <- ROSE(quartile ~ ., data = totrain)$data %>%
mutate(quartile = fct_relevel(quartile, "slow", after = Inf))
Error in ROSE(quartile ~ ., data = totrain) :
no se pudo encontrar la función "ROSE"
Comparación de las variables más importantes
(vip_mreg_rf_8_norm + vip_mreg_rf_9_norm + vip_mreg_rf_10_norm) |
(vip_mreg_rf_8 + vip_mreg_rf_9 + vip_mreg_rf_10)
totrain <- data_quartiles %>%
mutate(quartile = fct_collapse(quartile, fast = c("q1"), slow = c("q2","q3","q4"))) %>%
select(starts_with("mu"), quartile) %>%
filter(n!=10)
totest <- data_quartiles %>%
mutate(quartile = fct_collapse(quartile, fast = c("q1"), slow = c("q2","q3","q4"))) %>%
select(starts_with("mu"), quartile) %>%
filter(n==10)
set.seed(123)
rose_train <- ROSE(quartile ~ ., data = totrain)$data %>%
mutate(quartile = fct_relevel(quartile, "slow", after = Inf))
print(table(rose_train$quartile))
fast slow
4146 4254
set.seed(123)
trainIndex <- createDataPartition(rose_train$quartile, p = .8,
list = FALSE,
times = 1)
dataTrain <- rose_train[ trainIndex,]
dataTest <- rose_train[-trainIndex,]
Seeking for the outliers
data_outliers_normalized <- left_join(data_normalized %>%
mutate(id = as.double(as.character(id))), outliers)
Joining, by = c("n", "m", "id")
fitControl <- trainControl(
method = "repeatedcv",
number = 10,
repeats = 5,
classProbs = TRUE,
summaryFunction = twoClassSummary,
sampling = "down")
data_outliers_normalized
totrain <- data_outliers_normalized %>%
filter(n==8) %>%
select(starts_with("mu"), outlier)
set.seed(123)
trainIndex <- createDataPartition(totrain$outlier, p = .8,
list = FALSE,
times = 1)
dataTrain <- totrain[ trainIndex,]
dataTest <- totrain[-trainIndex,]
set.seed(123)
rf_8_outlier <- train(
outlier ~., data = dataTrain, method = "rf",
tuneLength = 10,
trControl = fitControl,
metric = "ROC"
)
vip_rf_8_outlier <- vip(rf_8_outlier)
pred <- predict(rf_8_outlier, dataTest)
confusionMatrix(data = pred, reference = dataTest$outlier, mode = "sens_spec")
Confusion Matrix and Statistics
Reference
Prediction yes no
yes 27 109
no 9 415
Accuracy : 0.7893
95% CI : (0.7531, 0.8224)
No Information Rate : 0.9357
P-Value [Acc > NIR] : 1
Kappa : 0.2363
Mcnemar's Test P-Value : <2e-16
Sensitivity : 0.75000
Specificity : 0.79198
Pos Pred Value : 0.19853
Neg Pred Value : 0.97877
Prevalence : 0.06429
Detection Rate : 0.04821
Detection Prevalence : 0.24286
Balanced Accuracy : 0.77099
'Positive' Class : yes
sens_rf_8_outlier <- sensitivity(pred, dataTest$outlier)
pred <- predict(rf_8_outlier, dataTest, type= "prob")
auc_rf_8_outlier <- AUC(pred$yes, ifelse(dataTest$outlier == "yes", 1, 0))
totrain <- data_outliers_normalized %>%
filter(n==9) %>%
select(starts_with("mu"), outlier)
set.seed(123)
trainIndex <- createDataPartition(totrain$outlier, p = .8,
list = FALSE,
times = 1)
dataTrain <- totrain[ trainIndex,]
dataTest <- totrain[-trainIndex,]
set.seed(123)
rf_9_outlier <- train(
outlier ~., data = dataTrain, method = "rf",
tuneLength = 10,
trControl = fitControl,
metric = "ROC"
)
vip_rf_9_outlier <- vip(rf_9_outlier)
pred <- predict(rf_9_outlier, dataTest)
confusionMatrix(data = pred, reference = dataTest$outlier, mode = "sens_spec")
Confusion Matrix and Statistics
Reference
Prediction yes no
yes 35 99
no 9 416
Accuracy : 0.8068
95% CI : (0.7716, 0.8387)
No Information Rate : 0.9213
P-Value [Acc > NIR] : 1
Kappa : 0.3117
Mcnemar's Test P-Value : <2e-16
Sensitivity : 0.79545
Specificity : 0.80777
Pos Pred Value : 0.26119
Neg Pred Value : 0.97882
Prevalence : 0.07871
Detection Rate : 0.06261
Detection Prevalence : 0.23971
Balanced Accuracy : 0.80161
'Positive' Class : yes
sens_rf_9_outlier <- sensitivity(pred, dataTest$outlier)
pred <- predict(rf_9_outlier, dataTest, type= "prob")
auc_rf_9_outlier <- AUC(pred$yes, ifelse(dataTest$outlier == "yes", 1, 0))
totrain <- data_outliers_normalized %>%
filter(n==10) %>%
select(starts_with("mu"), outlier)
set.seed(123)
trainIndex <- createDataPartition(totrain$outlier, p = .8,
list = FALSE,
times = 1)
dataTrain <- totrain[ trainIndex,]
dataTest <- totrain[-trainIndex,]
set.seed(123)
rf_10_outlier <- train(
outlier ~., data = dataTrain, method = "rf",
tuneLength = 10,
trControl = fitControl,
metric = "ROC"
)
vip_rf_10_outlier <- vip(rf_10_outlier)
pred <- predict(rf_10_outlier, dataTest)
confusionMatrix(data = pred, reference = dataTest$outlier, mode = "sens_spec")
Confusion Matrix and Statistics
Reference
Prediction yes no
yes 34 139
no 7 379
Accuracy : 0.7388
95% CI : (0.7003, 0.7748)
No Information Rate : 0.9267
P-Value [Acc > NIR] : 1
Kappa : 0.226
Mcnemar's Test P-Value : <2e-16
Sensitivity : 0.82927
Specificity : 0.73166
Pos Pred Value : 0.19653
Neg Pred Value : 0.98187
Prevalence : 0.07335
Detection Rate : 0.06082
Detection Prevalence : 0.30948
Balanced Accuracy : 0.78046
'Positive' Class : yes
sens_rf_10_outlier <- sensitivity(pred, dataTest$outlier)
pred <- predict(rf_10_outlier, dataTest, type= "prob")
auc_rf_10_outlier <- AUC(pred$yes, ifelse(dataTest$outlier == "yes", 1, 0))
vip_rf_8_outlier + vip_rf_9_outlier + vip_rf_10_outlier

totrain <- data_outliers_normalized %>%
select(starts_with("mu"), outlier)
set.seed(123)
trainIndex <- createDataPartition(totrain$outlier, p = .8,
list = FALSE,
times = 1)
dataTrain <- totrain[ trainIndex,]
dataTest <- totrain[-trainIndex,]
set.seed(123)
rf_all_outlier <- train(
#outlier ~., data = dataTrain, method = "rf",
outlier ~., data = dataTrain, method = "rf",
tuneLength = 8,
trControl = fitControl,
metric = "ROC"
)
pred <- predict(rf_all_outlier, dataTest)
postResample(pred = pred, obs = dataTest$outlier)
Accuracy Kappa
0.7641453 0.2541812
confusionMatrix(data = pred, reference = dataTest$outlier, mode = "sens_spec")
Confusion Matrix and Statistics
Reference
Prediction yes no
yes 102 377
no 19 1181
Accuracy : 0.7641
95% CI : (0.7431, 0.7843)
No Information Rate : 0.9279
P-Value [Acc > NIR] : 1
Kappa : 0.2542
Mcnemar's Test P-Value : <2e-16
Sensitivity : 0.84298
Specificity : 0.75802
Pos Pred Value : 0.21294
Neg Pred Value : 0.98417
Prevalence : 0.07207
Detection Rate : 0.06075
Detection Prevalence : 0.28529
Balanced Accuracy : 0.80050
'Positive' Class : yes
sens_rf_all_outlier <- sensitivity(pred, dataTest$outlier)
vip(rf_all_outlier)

pred <- predict(rf_all_outlier, dataTest, type= "prob")
auc_rf_all_outlier <- AUC(pred$yes, ifelse(dataTest$outlier == "yes", 1, 0))
vip(rf_all_outlier,
horizontal = FALSE,
aesthetics = list(width = .5)) +
theme_bw() +
scale_x_discrete(labels = function(x) parse(text=paste0("mu[", str_remove(x, "mu"), "]"))) +
ylab("Variable\nimportance") +
theme(text=element_text(size = 12, family="Times New Roman"),
axis.title.x = element_text(margin = margin(t = 10)))
sens_rf_8_outlier
[1] 0.75
auc_rf_8_outlier
[1] 0.8313454
sens_rf_9_outlier
[1] 0.7954545
auc_rf_9_outlier
[1] 0.8796778
sens_rf_10_outlier
[1] 0.8292683
auc_rf_10_outlier
[1] 0.8204869
sens_rf_all_outlier
[1] 0.8429752
auc_rf_all_outlier
[1] 0.863586
confusionMatrix(data = pred, reference = totest$outlier, mode = "sens_spec")
Confusion Matrix and Statistics
Reference
Prediction yes no
yes 169 811
no 38 1782
Accuracy : 0.6968
95% CI : (0.6794, 0.7138)
No Information Rate : 0.9261
P-Value [Acc > NIR] : 1
Kappa : 0.1853
Mcnemar's Test P-Value : <2e-16
Sensitivity : 0.81643
Specificity : 0.68723
Pos Pred Value : 0.17245
Neg Pred Value : 0.97912
Prevalence : 0.07393
Detection Rate : 0.06036
Detection Prevalence : 0.35000
Balanced Accuracy : 0.75183
'Positive' Class : yes
Ahora para los cuartiles
totrain <- data_quartiles_normalized %>%
filter(n!=10) %>%
select(starts_with("mu"), quartile) %>%
mutate(quartile = fct_collapse(quartile, fast = c("q1"), slow = c("q2","q3","q4")))
totest <- data_quartiles_normalized %>%
filter(n==10) %>%
select(starts_with("mu"), quartile) %>%
mutate(quartile = fct_collapse(quartile, fast = c("q1"), slow = c("q2","q3","q4")))
set.seed(123)
trainIndex <- createDataPartition(totrain$quartile, p = .8,
list = FALSE,
times = 1)
dataTrain <- totrain[ trainIndex,]
dataTest <- totrain[-trainIndex,]
set.seed(123)
rf_quartiles <- train(
quartile ~., data = dataTrain, method = "rf",
tuneLength = 10,
trControl = fitControl,
metric = "ROC"
)
pred <- predict(rf_quartiles, dataTest)
postResample(pred = pred, obs = dataTest$quartile)
Accuracy Kappa
0.6839286 0.3257143
# confusionMatrix(data = pred, reference = dataTest$quartile, mode = "sens_spec")
pred <- predict(rf_quartiles, totest)
postResample(pred = pred, obs = totest$quartile)
Accuracy Kappa
0.6967857 0.3713439
confusionMatrix(data = pred, reference = totest$quartile, mode = "sens_spec")
Confusion Matrix and Statistics
Reference
Prediction fast slow
fast 576 725
slow 124 1375
Accuracy : 0.6968
95% CI : (0.6794, 0.7138)
No Information Rate : 0.75
P-Value [Acc > NIR] : 1
Kappa : 0.3713
Mcnemar's Test P-Value : <2e-16
Sensitivity : 0.8229
Specificity : 0.6548
Pos Pred Value : 0.4427
Neg Pred Value : 0.9173
Prevalence : 0.2500
Detection Rate : 0.2057
Detection Prevalence : 0.4646
Balanced Accuracy : 0.7388
'Positive' Class : fast
pred <- predict(rf_quartiles, totest, type= "prob")
AUC(pred$fast, ifelse(totest$quartile == "fast", 1, 0))
[1] 0.8010837
vip(rf_quartiles)



LS0tCnRpdGxlOiAiVHJhaW5pbmciCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCmBgYHtyfQpsaWJyYXJ5KHRpZHl2ZXJzZSkKbGlicmFyeShjYXJldCkKYGBgCgojIERhdGEKCmBgYHtyIGVjaG89RkFMU0V9CmdncGxvdCh0aW1lcywgYWVzKHg9YXMubnVtZXJpYyhtKSx5PWV4ZWNfdGltZSxjb2xvcj1xdWFydGlsZSxncm91cD1tKSkgKyAKICBnZW9tX2ppdHRlcihoZWlnaHQgPSAwKSArCiAgZ2VvbV9obGluZShhZXMoeWludGVyY2VwdCA9IG1lYW4oZXhlY190aW1lKSkpICsKICBnZW9tX2hsaW5lKGFlcyh5aW50ZXJjZXB0ID0gbWVkaWFuKGV4ZWNfdGltZSkpLCBsaW5ldHlwZSA9ICJkYXNoZWQiKSArCiAgZmFjZXRfd3JhcCh+biwgc2NhbGVzID0gImZyZWVfeCIpICsKICBjb29yZF9mbGlwKCkgKwogIHhsYWIoIiIpICsgeWxhYigiIikgKwogIHRoZW1lX2xpZ2h0KCkKYGBgCgpgYGB7cn0KZ2dwbG90KHRpbWVzLCBhZXMoZXhlY190aW1lKSkgKwogIGdlb21fYm94cGxvdCgpICsKICBmYWNldF93cmFwKG5+Liwgc2NhbGVzID0gImZyZWVfeCIsIG5yb3cgPSAzLCBzdHJpcC5wb3NpdGlvbiA9ICJyaWdodCIpICArCiAgdGhlbWVfYncoKSArCiAgc2NhbGVfeF9jb250aW51b3VzKG4uYnJlYWtzID0gMTApICsKICB4bGFiKCIiKSArIHlsYWIoIiIpICsKICB0aGVtZShheGlzLnRleHQueSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICBheGlzLnRpY2tzLnkgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgcGFuZWwuZ3JpZC5tYWpvci55ID0gZWxlbWVudF9ibGFuaygpKQpgYGAKCk51bWJlcnMgZGl2aWRlZCBieSBxdWFydGlsZXMgaW4gb3JkZXIgdG8gZGV0ZXJtaW5lIHRoZSBwcm9maWxlcyBvZiByYW5raW5ncyB0aGF0IGFyZSBzbG93IGFuZCBmYXN0LiBUaGUgcHJvZmlsZXMgYXJlIGRpdmlkZWQgaW4gZm91ciBlcXVhbCBwYXJ0cyBjb25zaWRlcmluZyB0aGUgbnVtYmVyIG9mIGFsdGVybmF0aXZlcyBhbmQgb25lIHF1YXJ0ZXIgaXMgdGFraW5nIGFzIGZhc3QgYW5kIHRoZSBvdGhlciBjb25zaWRlcmVkIGFzIHNsb3cuCgpgYGB7ciBlY2hvPUZBTFNFfQpnZ3Bsb3QodGltZXMgJT4lIGNvdW50KG4sbSxxdWFydGlsZSksIGFlcyhtLG5uLGZpbGw9cXVhcnRpbGUpKSArCiAgZ2VvbV9iYXIoYWVzKGFscGhhID0gYXMubnVtZXJpYyhhcy5jaGFyYWN0ZXIobSkpJSUyPT0wKSxzdGF0PSJpZGVudGl0eSIsIHBvc2l0aW9uPSJmaWxsIikgKwogIGdlb21fdGV4dChhZXMobGFiZWw9bm4pLHBvc2l0aW9uID0gcG9zaXRpb25fZmlsbCh2anVzdCA9IDAuNSksIGFuZ2xlID0gOTApICsKICBmYWNldF9ncmlkKC5+bikgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IC43NSkgKwogIGdlb21faGxpbmUoeWludGVyY2VwdCA9IC41KSArCiAgZ2VvbV9obGluZSh5aW50ZXJjZXB0ID0gLjI1KSArCiAgc2NhbGVfYWxwaGFfZGlzY3JldGUocmFuZ2UgPSBjKDAuNiwxKSkgKwogIHRoZW1lX2J3KCkgKwogIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIikKYGBgCmBgYHtyfQojIEZvciB0aGUgcmVnZ3Jlc2lvbiBwcm9ibGVtCiMgZml0Q29udHJvbCA8LSB0cmFpbkNvbnRyb2woCiMgICBtZXRob2QgPSAicmVwZWF0ZWRjdiIsCiMgICBudW1iZXIgPSA1LAojICAgcmVwZWF0cyA9IDIpCgpmaXRDb250cm9sIDwtIHRyYWluQ29udHJvbCgKICBtZXRob2QgPSAicmVwZWF0ZWRjdiIsCiAgbnVtYmVyID0gNSwKICByZXBlYXRzID0gMiwKICBjbGFzc1Byb2JzID0gVFJVRSwKICBzdW1tYXJ5RnVuY3Rpb24gPSBwclN1bW1hcnkpCmBgYAoKIyBQcmVkaWN0aW5nIGV4ZWN1dGlvbiB0aW1lIGZvciBwcm9maWxlcyBvZiBhIGZpeGVkIHNpemUKCmBgYHtyfQpkYXRhX3F1YXJ0aWxlcyA8LSBsZWZ0X2pvaW4ocHJlZGljdF90aW1lcyAlPiUgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShpZCA9IGFzLmRvdWJsZShhcy5jaGFyYWN0ZXIoaWQpKSksIHRpbWVzKSAKZGF0YV9xdWFydGlsZXMKYGBgCgpgYGB7ciBlY2hvPUZBTFNFfQpkYXRhX3F1YXJ0aWxlc19ub3JtYWxpemVkIDwtIGxlZnRfam9pbihkYXRhX25vcm1hbGl6ZWQgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKGlkID0gYXMuZG91YmxlKGFzLmNoYXJhY3RlcihpZCkpKSwgdGltZXMpIApkYXRhX3F1YXJ0aWxlc19ub3JtYWxpemVkCmBgYAoKYGBge3J9CiMgRml0IGNvbnRyb2wgcGFyYSAKZml0Q29udHJvbCA8LSB0cmFpbkNvbnRyb2woCiAgbWV0aG9kID0gInJlcGVhdGVkY3YiLAogIG51bWJlciA9IDUsCiAgcmVwZWF0cyA9IDIsCiAgY2xhc3NQcm9icyA9IFRSVUUsCiAgc3VtbWFyeUZ1bmN0aW9uID0gcHJTdW1tYXJ5KQpgYGAKClRyYWluaW5nIDI1JS03NSUKCmBgYHtyfQojIERhIG11eSBtYWxvcyByZXN1bHRhZG9zIHBvcnF1ZSBlc3TDoSBkZXNiYWxhbmNlYWRvCiMgIyBQYXJhIG4gPSAxMAojIHRvdHJhaW4gPC0gZGF0YV9xdWFydGlsZXMgJT4lIAojICAgZmlsdGVyKG49PTEwKSAlPiUgCiMgICBtdXRhdGUocXVhcnRpbGUgPSBmY3RfY29sbGFwc2UocXVhcnRpbGUsIGZhc3QgPSBjKCJxMSIpLCBzbG93ID0gYygicTIiLCJxMyIsInE0IikpKSAlPiUKIyAgIHNlbGVjdChzdGFydHNfd2l0aCgibXUiKSwgcXVhcnRpbGUpIAojIHNldC5zZWVkKDEyMykKIyB0cmFpbkluZGV4IDwtIGNyZWF0ZURhdGFQYXJ0aXRpb24odG90cmFpbiRxdWFydGlsZSwgcCA9IC44LCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdCA9IEZBTFNFLCAKIyAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGltZXMgPSAxKQojIGRhdGFUcmFpbiA8LSB0b3RyYWluWyB0cmFpbkluZGV4LF0KIyBkYXRhVGVzdCAgPC0gdG90cmFpblstdHJhaW5JbmRleCxdCiMgc2V0LnNlZWQoMTIzKQojIG1jbGFzX3JmXzEwIDwtIHRyYWluKAojICAgcXVhcnRpbGUgfi4sIGRhdGEgPSBkYXRhVHJhaW4sIAojICAgbWV0aG9kID0gInJmIiwKIyAgIHR1bmVMZW5ndGggPSAzLAojICAgdHJDb250cm9sID0gZml0Q29udHJvbCwKIyAgIG1ldHJpYyA9ICJBVUMiCiMgKQojIG1jbGFzX3JmXzEwCmBgYAoKYGBge3J9CmxpYnJhcnkoUk9TRSkKYGBgCgpQYXJhIG4gPSAxMCBjb24gbG9zIGRhdG9zIG5vcm1hbGl6YWRvcwoKYGBge3J9CnRvdHJhaW4gPC0gZGF0YV9xdWFydGlsZXNfbm9ybWFsaXplZCAlPiUgCiAgZmlsdGVyKG49PTEwKSAlPiUKICBtdXRhdGUocXVhcnRpbGUgPSBmY3RfY29sbGFwc2UocXVhcnRpbGUsIGZhc3QgPSBjKCJxMSIpLCBzbG93ID0gYygicTIiLCJxMyIsInE0IikpKSAlPiUKICBzZWxlY3Qoc3RhcnRzX3dpdGgoIm11IiksIHF1YXJ0aWxlKQogIApzZXQuc2VlZCgxMjMpIApyb3NlX3RyYWluIDwtIFJPU0UocXVhcnRpbGUgfiAuLCBkYXRhICA9IHRvdHJhaW4pJGRhdGEgJT4lCiAgbXV0YXRlKHF1YXJ0aWxlID0gZmN0X3JlbGV2ZWwocXVhcnRpbGUsICJzbG93IiwgYWZ0ZXIgPSBJbmYpKQojIHByaW50KHRhYmxlKHJvc2VfdHJhaW4kcXVhcnRpbGUpKQoKc2V0LnNlZWQoMTIzKQp0cmFpbkluZGV4IDwtIGNyZWF0ZURhdGFQYXJ0aXRpb24ocm9zZV90cmFpbiRxdWFydGlsZSwgcCA9IC44LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3QgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lcyA9IDEpCmRhdGFUcmFpbiA8LSByb3NlX3RyYWluWyB0cmFpbkluZGV4LF0KZGF0YVRlc3QgIDwtIHJvc2VfdHJhaW5bLXRyYWluSW5kZXgsXQoKc2V0LnNlZWQoMTIzKQpyZl8xMF9yb3NlX25vcm0gPC0gdHJhaW4oCiAgcXVhcnRpbGUgfi4sIGRhdGEgPSBkYXRhVHJhaW4sIG1ldGhvZCA9ICJyZiIsCiAgdHVuZUxlbmd0aCA9IDMsCiAgdHJDb250cm9sID0gZml0Q29udHJvbCwKICBtZXRyaWMgPSAiQVVDIgopCgp2aXBfcmZfMTBfcm9zZV9ub3JtIDwtIHZpcChyZl8xMF9yb3NlX25vcm0pCmNvbmZ1c2lvbk1hdHJpeChyZl8xMF9yb3NlX25vcm0pCmBgYAoKClkgZW4gdGVzdDoKCmBgYHtyfQpwcmVkIDwtIHByZWRpY3QocmZfMTBfcm9zZV9ub3JtLCBkYXRhVGVzdCkKcG9zdFJlc2FtcGxlKHByZWQgPSBwcmVkLCBvYnMgPSBkYXRhVGVzdCRxdWFydGlsZSkKY29uZnVzaW9uTWF0cml4KGRhdGEgPSBwcmVkLCByZWZlcmVuY2UgPSBkYXRhVGVzdCRxdWFydGlsZSwgbW9kZSA9ICJwcmVjX3JlY2FsbCIpCmBgYAoKWSBzaW4gbm9ybWFsaXphcjoKCmBgYHtyfQpmaXRDb250cm9sIDwtIHRyYWluQ29udHJvbCgKICBtZXRob2QgPSAicmVwZWF0ZWRjdiIsCiAgbnVtYmVyID0gNSwKICByZXBlYXRzID0gMiwKICBjbGFzc1Byb2JzID0gVFJVRSwKICBzdW1tYXJ5RnVuY3Rpb24gPSBwclN1bW1hcnksCiAgc2FtcGxpbmcgPSAidXAiKQoKZGF0YV9xdWFydGlsZXMgPC0gbGVmdF9qb2luKHByZWRpY3RfdGltZXMgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGUoaWQgPSBhcy5kb3VibGUoaWQpKSwgdGltZXMpIAoKdG90cmFpbiA8LSBkYXRhX3F1YXJ0aWxlcyAlPiUgCiAgZmlsdGVyKG49PTEwKSAlPiUKICBtdXRhdGUocXVhcnRpbGUgPSBmY3RfY29sbGFwc2UocXVhcnRpbGUsIGZhc3QgPSBjKCJxMSIpLCBzbG93ID0gYygicTIiLCJxMyIsInE0IikpKSAlPiUKICBzZWxlY3Qoc3RhcnRzX3dpdGgoIm11IiksIHF1YXJ0aWxlKQogIAp0cmFpbkluZGV4IDwtIGNyZWF0ZURhdGFQYXJ0aXRpb24odG90cmFpbiRxdWFydGlsZSwgcCA9IC44LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3QgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lcyA9IDEpCgpkYXRhVHJhaW4gPC0gdG90cmFpblsgdHJhaW5JbmRleCxdCmRhdGFUZXN0ICA8LSB0b3RyYWluWy10cmFpbkluZGV4LF0KCnJmXzEwX3Jvc2UgPC0gdHJhaW4oCiAgcXVhcnRpbGUgfi4sIGRhdGEgPSBkYXRhVHJhaW4sIG1ldGhvZCA9ICJyZiIsCiAgdHVuZUxlbmd0aCA9IDMsCiAgdHJDb250cm9sID0gZml0Q29udHJvbCwKICBtZXRyaWMgPSAiQVVDIgopCnJmXzEwX3Jvc2UKYGBgCgoKCgpgYGB7cn0KZGF0YV9xdWFydGlsZXMgPC0gbGVmdF9qb2luKHByZWRpY3RfdGltZXMgJT4lIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICBtdXRhdGUoaWQgPSBhcy5kb3VibGUoaWQpKSwgdGltZXMpIAoKdG90cmFpbiA8LSBkYXRhX3F1YXJ0aWxlcyAlPiUgCiAgZmlsdGVyKG49PTEwKSAlPiUKICBtdXRhdGUocXVhcnRpbGUgPSBmY3RfY29sbGFwc2UocXVhcnRpbGUsIGZhc3QgPSBjKCJxMSIpLCBzbG93ID0gYygicTIiLCJxMyIsInE0IikpKSAlPiUKICBzZWxlY3Qoc3RhcnRzX3dpdGgoIm11IiksIHF1YXJ0aWxlKQogIAp0cmFpbkluZGV4IDwtIGNyZWF0ZURhdGFQYXJ0aXRpb24odG90cmFpbiRxdWFydGlsZSwgcCA9IC44LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3QgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lcyA9IDEpCgpkYXRhVHJhaW4gPC0gdG90cmFpblsgdHJhaW5JbmRleCxdCmRhdGFUZXN0ICA8LSB0b3RyYWluWy10cmFpbkluZGV4LF0KCnNldC5zZWVkKDEyMykgCnJvc2VfdHJhaW4gPC0gUk9TRShxdWFydGlsZSB+IC4sIGRhdGEgID0gZGF0YVRyYWluKSRkYXRhICU+JQogIG11dGF0ZShxdWFydGlsZSA9IGZjdF9yZWxldmVsKHF1YXJ0aWxlLCAic2xvdyIsIGFmdGVyID0gSW5mKSkKCgpzZXQuc2VlZCgxMjMpCnJmXzEwX3Jvc2UgPC0gdHJhaW4oCiAgcXVhcnRpbGUgfi4sIGRhdGEgPSByb3NlX3RyYWluLCBtZXRob2QgPSAicmYiLAogIHR1bmVMZW5ndGggPSAzLAogIHRyQ29udHJvbCA9IGZpdENvbnRyb2wsCiAgbWV0cmljID0gIkFVQyIKKQoKdmlwX3JmXzEwX3Jvc2UgPC0gdmlwKHJmXzEwX3Jvc2UpCmNvbmZ1c2lvbk1hdHJpeChyZl8xMF9yb3NlKQpgYGAKCmBgYHtyfQpwcmVkIDwtIHByZWRpY3QocmZfMTBfcm9zZSwgZGF0YVRlc3QpCnBvc3RSZXNhbXBsZShwcmVkID0gcHJlZCwgb2JzID0gZGF0YVRlc3QkcXVhcnRpbGUpCmNvbmZ1c2lvbk1hdHJpeChkYXRhID0gcHJlZCwgcmVmZXJlbmNlID0gZGF0YVRlc3QkcXVhcnRpbGUsIG1vZGUgPSAicHJlY19yZWNhbGwiKQpgYGAKCgoKCgoKYGBge3J9CmRhdGFfcXVhcnRpbGVzIDwtIGxlZnRfam9pbihwcmVkaWN0X3RpbWVzICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbXV0YXRlKGlkID0gYXMuZG91YmxlKGlkKSksIHRpbWVzKSAKCnRvdHJhaW4gPC0gZGF0YV9xdWFydGlsZXMgJT4lIAogIGZpbHRlcihuPT0xMCkgJT4lCiAgbXV0YXRlKHF1YXJ0aWxlID0gZmN0X2NvbGxhcHNlKHF1YXJ0aWxlLCBmYXN0ID0gYygicTEiKSwgc2xvdyA9IGMoInEyIiwicTMiLCJxNCIpKSkgJT4lCiAgc2VsZWN0KHN0YXJ0c193aXRoKCJtdSIpLCBxdWFydGlsZSkKICAKc2V0LnNlZWQoMTIzKSAKcm9zZV90cmFpbiA8LSBST1NFKHF1YXJ0aWxlIH4gLiwgZGF0YSAgPSB0b3RyYWluKSRkYXRhICU+JQogIG11dGF0ZShxdWFydGlsZSA9IGZjdF9yZWxldmVsKHF1YXJ0aWxlLCAic2xvdyIsIGFmdGVyID0gSW5mKSkKIyBwcmludCh0YWJsZShyb3NlX3RyYWluJHF1YXJ0aWxlKSkKCnNldC5zZWVkKDEyMykKdHJhaW5JbmRleCA8LSBjcmVhdGVEYXRhUGFydGl0aW9uKHJvc2VfdHJhaW4kcXVhcnRpbGUsIHAgPSAuOCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0ID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGltZXMgPSAxKQpkYXRhVHJhaW4gPC0gcm9zZV90cmFpblsgdHJhaW5JbmRleCxdCmRhdGFUZXN0ICA8LSByb3NlX3RyYWluWy10cmFpbkluZGV4LF0KCnNldC5zZWVkKDEyMykKcmZfMTBfcm9zZSA8LSB0cmFpbigKICBxdWFydGlsZSB+LiwgZGF0YSA9IGRhdGFUcmFpbiwgbWV0aG9kID0gInJmIiwKICB0dW5lTGVuZ3RoID0gMywKICB0ckNvbnRyb2wgPSBmaXRDb250cm9sLAogIG1ldHJpYyA9ICJBVUMiCikKCnZpcF9yZl8xMF9yb3NlIDwtIHZpcChyZl8xMF9yb3NlKQpjb25mdXNpb25NYXRyaXgocmZfMTBfcm9zZSkKYGBgCgpgYGB7cn0Kc2V0LnNlZWQoMTIzKQpycGFydF8xMF9yb3NlX25vcm0gPC0gdHJhaW4oCiAgcXVhcnRpbGUgfi4sIGRhdGEgPSBkYXRhVHJhaW4sIG1ldGhvZCA9ICJubmV0IiwKICB0dW5lTGVuZ3RoID0gMywKICB0ckNvbnRyb2wgPSBmaXRDb250cm9sLAogIHByZVByb2Nlc3MgPSBjKCJjZW50ZXIiLCJzY2FsZSIpLAogIG1ldHJpYyA9ICJBVUMiCikKYGBgCgoKCgpDb21wYXJhY2nDs24gZGUgbGFzIHZhcmlhYmxlcyBtw6FzIGltcG9ydGFudGVzCgpgYGB7cn0KKHZpcF9tcmVnX3JmXzhfbm9ybSArIHZpcF9tcmVnX3JmXzlfbm9ybSArIHZpcF9tcmVnX3JmXzEwX25vcm0pIHwKKHZpcF9tcmVnX3JmXzggKyB2aXBfbXJlZ19yZl85ICsgdmlwX21yZWdfcmZfMTApCmBgYAoKCgoKCgoKCgoKYGBge3J9CnRvdHJhaW4gPC0gZGF0YV9xdWFydGlsZXMgJT4lIAogIG11dGF0ZShxdWFydGlsZSA9IGZjdF9jb2xsYXBzZShxdWFydGlsZSwgZmFzdCA9IGMoInExIiksIHNsb3cgPSBjKCJxMiIsInEzIiwicTQiKSkpICU+JQogIHNlbGVjdChzdGFydHNfd2l0aCgibXUiKSwgcXVhcnRpbGUpICU+JQogIGZpbHRlcihuIT0xMCkKdG90ZXN0IDwtIGRhdGFfcXVhcnRpbGVzICU+JSAKICBtdXRhdGUocXVhcnRpbGUgPSBmY3RfY29sbGFwc2UocXVhcnRpbGUsIGZhc3QgPSBjKCJxMSIpLCBzbG93ID0gYygicTIiLCJxMyIsInE0IikpKSAlPiUKICBzZWxlY3Qoc3RhcnRzX3dpdGgoIm11IiksIHF1YXJ0aWxlKSAlPiUKICBmaWx0ZXIobj09MTApCgpzZXQuc2VlZCgxMjMpCnJvc2VfdHJhaW4gPC0gUk9TRShxdWFydGlsZSB+IC4sIGRhdGEgID0gdG90cmFpbikkZGF0YSAlPiUKICBtdXRhdGUocXVhcnRpbGUgPSBmY3RfcmVsZXZlbChxdWFydGlsZSwgInNsb3ciLCBhZnRlciA9IEluZikpCnByaW50KHRhYmxlKHJvc2VfdHJhaW4kcXVhcnRpbGUpKQoKc2V0LnNlZWQoMTIzKQp0cmFpbkluZGV4IDwtIGNyZWF0ZURhdGFQYXJ0aXRpb24ocm9zZV90cmFpbiRxdWFydGlsZSwgcCA9IC44LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3QgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lcyA9IDEpCmRhdGFUcmFpbiA8LSByb3NlX3RyYWluWyB0cmFpbkluZGV4LF0KZGF0YVRlc3QgIDwtIHJvc2VfdHJhaW5bLXRyYWluSW5kZXgsXQpgYGAKCgojIFNlZWtpbmcgZm9yIHRoZSBvdXRsaWVycwoKYGBge3J9CmRhdGFfb3V0bGllcnNfbm9ybWFsaXplZCA8LSBsZWZ0X2pvaW4oZGF0YV9ub3JtYWxpemVkICU+JSAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIG11dGF0ZShpZCA9IGFzLmRvdWJsZShhcy5jaGFyYWN0ZXIoaWQpKSksIG91dGxpZXJzKSAKCmZpdENvbnRyb2wgPC0gdHJhaW5Db250cm9sKAogIG1ldGhvZCA9ICJyZXBlYXRlZGN2IiwKICBudW1iZXIgPSAxMCwKICByZXBlYXRzID0gNSwKICBjbGFzc1Byb2JzID0gVFJVRSwKICBzdW1tYXJ5RnVuY3Rpb24gPSB0d29DbGFzc1N1bW1hcnksCiAgc2FtcGxpbmcgPSAiZG93biIpCgpkYXRhX291dGxpZXJzX25vcm1hbGl6ZWQKYGBgCgpgYGB7cn0KdG90cmFpbiA8LSBkYXRhX291dGxpZXJzX25vcm1hbGl6ZWQgJT4lIAogIGZpbHRlcihuPT04KSAlPiUKICBzZWxlY3Qoc3RhcnRzX3dpdGgoIm11IiksIG91dGxpZXIpCiAgCnNldC5zZWVkKDEyMykKdHJhaW5JbmRleCA8LSBjcmVhdGVEYXRhUGFydGl0aW9uKHRvdHJhaW4kb3V0bGllciwgcCA9IC44LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3QgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lcyA9IDEpCgpkYXRhVHJhaW4gPC0gdG90cmFpblsgdHJhaW5JbmRleCxdCmRhdGFUZXN0ICA8LSB0b3RyYWluWy10cmFpbkluZGV4LF0KCnNldC5zZWVkKDEyMykKcmZfOF9vdXRsaWVyIDwtIHRyYWluKAogIG91dGxpZXIgfi4sIGRhdGEgPSBkYXRhVHJhaW4sIG1ldGhvZCA9ICJyZiIsCiAgdHVuZUxlbmd0aCA9IDEwLAogIHRyQ29udHJvbCA9IGZpdENvbnRyb2wsCiAgbWV0cmljID0gIlJPQyIKKQoKdmlwX3JmXzhfb3V0bGllciA8LSB2aXAocmZfOF9vdXRsaWVyKQpwcmVkIDwtIHByZWRpY3QocmZfOF9vdXRsaWVyLCBkYXRhVGVzdCkKY29uZnVzaW9uTWF0cml4KGRhdGEgPSBwcmVkLCByZWZlcmVuY2UgPSBkYXRhVGVzdCRvdXRsaWVyLCBtb2RlID0gInNlbnNfc3BlYyIpCnNlbnNfcmZfOF9vdXRsaWVyIDwtIHNlbnNpdGl2aXR5KHByZWQsIGRhdGFUZXN0JG91dGxpZXIpCnByZWQgPC0gcHJlZGljdChyZl84X291dGxpZXIsIGRhdGFUZXN0LCB0eXBlPSAicHJvYiIpCmF1Y19yZl84X291dGxpZXIgPC0gQVVDKHByZWQkeWVzLCBpZmVsc2UoZGF0YVRlc3Qkb3V0bGllciA9PSAieWVzIiwgMSwgMCkpCmBgYAoKYGBge3J9CnRvdHJhaW4gPC0gZGF0YV9vdXRsaWVyc19ub3JtYWxpemVkICU+JSAKICBmaWx0ZXIobj09OSkgJT4lCiAgc2VsZWN0KHN0YXJ0c193aXRoKCJtdSIpLCBvdXRsaWVyKQogIApzZXQuc2VlZCgxMjMpCnRyYWluSW5kZXggPC0gY3JlYXRlRGF0YVBhcnRpdGlvbih0b3RyYWluJG91dGxpZXIsIHAgPSAuOCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0ID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGltZXMgPSAxKQoKZGF0YVRyYWluIDwtIHRvdHJhaW5bIHRyYWluSW5kZXgsXQpkYXRhVGVzdCAgPC0gdG90cmFpblstdHJhaW5JbmRleCxdCgpzZXQuc2VlZCgxMjMpCnJmXzlfb3V0bGllciA8LSB0cmFpbigKICBvdXRsaWVyIH4uLCBkYXRhID0gZGF0YVRyYWluLCBtZXRob2QgPSAicmYiLAogIHR1bmVMZW5ndGggPSAxMCwKICB0ckNvbnRyb2wgPSBmaXRDb250cm9sLAogIG1ldHJpYyA9ICJST0MiCikKCnZpcF9yZl85X291dGxpZXIgPC0gdmlwKHJmXzlfb3V0bGllcikKcHJlZCA8LSBwcmVkaWN0KHJmXzlfb3V0bGllciwgZGF0YVRlc3QpCmNvbmZ1c2lvbk1hdHJpeChkYXRhID0gcHJlZCwgcmVmZXJlbmNlID0gZGF0YVRlc3Qkb3V0bGllciwgbW9kZSA9ICJzZW5zX3NwZWMiKQpzZW5zX3JmXzlfb3V0bGllciA8LSBzZW5zaXRpdml0eShwcmVkLCBkYXRhVGVzdCRvdXRsaWVyKQpwcmVkIDwtIHByZWRpY3QocmZfOV9vdXRsaWVyLCBkYXRhVGVzdCwgdHlwZT0gInByb2IiKQphdWNfcmZfOV9vdXRsaWVyIDwtIEFVQyhwcmVkJHllcywgaWZlbHNlKGRhdGFUZXN0JG91dGxpZXIgPT0gInllcyIsIDEsIDApKQpgYGAKCmBgYHtyfQp0b3RyYWluIDwtIGRhdGFfb3V0bGllcnNfbm9ybWFsaXplZCAlPiUgCiAgZmlsdGVyKG49PTEwKSAlPiUKICBzZWxlY3Qoc3RhcnRzX3dpdGgoIm11IiksIG91dGxpZXIpCiAgCnNldC5zZWVkKDEyMykKdHJhaW5JbmRleCA8LSBjcmVhdGVEYXRhUGFydGl0aW9uKHRvdHJhaW4kb3V0bGllciwgcCA9IC44LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3QgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lcyA9IDEpCgpkYXRhVHJhaW4gPC0gdG90cmFpblsgdHJhaW5JbmRleCxdCmRhdGFUZXN0ICA8LSB0b3RyYWluWy10cmFpbkluZGV4LF0KCnNldC5zZWVkKDEyMykKcmZfMTBfb3V0bGllciA8LSB0cmFpbigKICBvdXRsaWVyIH4uLCBkYXRhID0gZGF0YVRyYWluLCBtZXRob2QgPSAicmYiLAogIHR1bmVMZW5ndGggPSAxMCwKICB0ckNvbnRyb2wgPSBmaXRDb250cm9sLAogIG1ldHJpYyA9ICJST0MiCikKCnZpcF9yZl8xMF9vdXRsaWVyIDwtIHZpcChyZl8xMF9vdXRsaWVyKQpwcmVkIDwtIHByZWRpY3QocmZfMTBfb3V0bGllciwgZGF0YVRlc3QpCmNvbmZ1c2lvbk1hdHJpeChkYXRhID0gcHJlZCwgcmVmZXJlbmNlID0gZGF0YVRlc3Qkb3V0bGllciwgbW9kZSA9ICJzZW5zX3NwZWMiKQpzZW5zX3JmXzEwX291dGxpZXIgPC0gc2Vuc2l0aXZpdHkocHJlZCwgZGF0YVRlc3Qkb3V0bGllcikKcHJlZCA8LSBwcmVkaWN0KHJmXzEwX291dGxpZXIsIGRhdGFUZXN0LCB0eXBlPSAicHJvYiIpCmF1Y19yZl8xMF9vdXRsaWVyIDwtIEFVQyhwcmVkJHllcywgaWZlbHNlKGRhdGFUZXN0JG91dGxpZXIgPT0gInllcyIsIDEsIDApKQpgYGAKCmBgYHtyfQp2aXBfcmZfOF9vdXRsaWVyICsgdmlwX3JmXzlfb3V0bGllciArIHZpcF9yZl8xMF9vdXRsaWVyCmBgYAoKCmBgYHtyfQp0b3RyYWluIDwtIGRhdGFfb3V0bGllcnNfbm9ybWFsaXplZCAlPiUgCiAgc2VsZWN0KHN0YXJ0c193aXRoKCJtdSIpLCBvdXRsaWVyKQogIApzZXQuc2VlZCgxMjMpCnRyYWluSW5kZXggPC0gY3JlYXRlRGF0YVBhcnRpdGlvbih0b3RyYWluJG91dGxpZXIsIHAgPSAuOCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0ID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGltZXMgPSAxKQoKZGF0YVRyYWluIDwtIHRvdHJhaW5bIHRyYWluSW5kZXgsXQpkYXRhVGVzdCAgPC0gdG90cmFpblstdHJhaW5JbmRleCxdCgpzZXQuc2VlZCgxMjMpCnJmX2FsbF9vdXRsaWVyIDwtIHRyYWluKAogICNvdXRsaWVyIH4uLCBkYXRhID0gZGF0YVRyYWluLCBtZXRob2QgPSAicmYiLAogIG91dGxpZXIgfi4sIGRhdGEgPSBkYXRhVHJhaW4sIG1ldGhvZCA9ICJyZiIsCiAgdHVuZUxlbmd0aCA9IDgsCiAgdHJDb250cm9sID0gZml0Q29udHJvbCwKICBtZXRyaWMgPSAiUk9DIgopCgpwcmVkIDwtIHByZWRpY3QocmZfYWxsX291dGxpZXIsIGRhdGFUZXN0KQpwb3N0UmVzYW1wbGUocHJlZCA9IHByZWQsIG9icyA9IGRhdGFUZXN0JG91dGxpZXIpCmNvbmZ1c2lvbk1hdHJpeChkYXRhID0gcHJlZCwgcmVmZXJlbmNlID0gZGF0YVRlc3Qkb3V0bGllciwgbW9kZSA9ICJzZW5zX3NwZWMiKQpzZW5zX3JmX2FsbF9vdXRsaWVyIDwtIHNlbnNpdGl2aXR5KHByZWQsIGRhdGFUZXN0JG91dGxpZXIpCgp2aXAocmZfYWxsX291dGxpZXIpCgpwcmVkIDwtIHByZWRpY3QocmZfYWxsX291dGxpZXIsIGRhdGFUZXN0LCB0eXBlPSAicHJvYiIpCmF1Y19yZl9hbGxfb3V0bGllciA8LSBBVUMocHJlZCR5ZXMsIGlmZWxzZShkYXRhVGVzdCRvdXRsaWVyID09ICJ5ZXMiLCAxLCAwKSkKYGBgCgpgYGB7cn0KdmlwKHJmX2FsbF9vdXRsaWVyLCAKICAgIGhvcml6b250YWwgPSBGQUxTRSwKICAgIGFlc3RoZXRpY3MgPSBsaXN0KHdpZHRoID0gLjUpKSArCiAgdGhlbWVfYncoKSArIAogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gZnVuY3Rpb24oeCkgcGFyc2UodGV4dD1wYXN0ZTAoIm11WyIsIHN0cl9yZW1vdmUoeCwgIm11IiksICJdIikpKSArCiAgeWxhYigiVmFyaWFibGVcbmltcG9ydGFuY2UiKSArCiAgdGhlbWUodGV4dD1lbGVtZW50X3RleHQoc2l6ZSA9IDEyLCBmYW1pbHk9IlRpbWVzIE5ldyBSb21hbiIpLAogICAgICAgIGF4aXMudGl0bGUueCA9IGVsZW1lbnRfdGV4dChtYXJnaW4gPSBtYXJnaW4odCA9IDEwKSkpCiAgCmBgYAoKCmBgYHtyfQpzZW5zX3JmXzhfb3V0bGllcgphdWNfcmZfOF9vdXRsaWVyCnNlbnNfcmZfOV9vdXRsaWVyCmF1Y19yZl85X291dGxpZXIKc2Vuc19yZl8xMF9vdXRsaWVyCmF1Y19yZl8xMF9vdXRsaWVyCnNlbnNfcmZfYWxsX291dGxpZXIKYXVjX3JmX2FsbF9vdXRsaWVyCmBgYAoKCmBgYHtyfQojIGZpdENvbnRyb2wgPC0gdHJhaW5Db250cm9sKAojICAgbWV0aG9kID0gInJlcGVhdGVkY3YiLAojICAgbnVtYmVyID0gMywKIyAgIHJlcGVhdHMgPSA1LAojICAgY2xhc3NQcm9icyA9IFRSVUUsCiMgICBzdW1tYXJ5RnVuY3Rpb24gPSB0d29DbGFzc1N1bW1hcnksCiMgICBzYW1wbGluZyA9ICJkb3duIikKCnRvdHJhaW4gPC0gZGF0YV9vdXRsaWVyc19ub3JtYWxpemVkICU+JSAKICBmaWx0ZXIobiE9MTApICU+JQogIHNlbGVjdChzdGFydHNfd2l0aCgibXUiKSwgb3V0bGllcikKCnRvdGVzdCA8LSBkYXRhX291dGxpZXJzX25vcm1hbGl6ZWQgJT4lIAogIGZpbHRlcihuPT0xMCkgJT4lCiAgc2VsZWN0KHN0YXJ0c193aXRoKCJtdSIpLCBvdXRsaWVyKSAKICAKc2V0LnNlZWQoMTIzKQp0cmFpbkluZGV4IDwtIGNyZWF0ZURhdGFQYXJ0aXRpb24odG90cmFpbiRvdXRsaWVyLCBwID0gLjgsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgbGlzdCA9IEZBTFNFLCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHRpbWVzID0gMSkKCmRhdGFUcmFpbiA8LSB0b3RyYWluWyB0cmFpbkluZGV4LF0KZGF0YVRlc3QgIDwtIHRvdHJhaW5bLXRyYWluSW5kZXgsXQoKc2V0LnNlZWQoMTIzKQpyZl9hbGxfb3V0bGllcjIgPC0gdHJhaW4oCiAgb3V0bGllciB+LiwgZGF0YSA9IGRhdGFUcmFpbiwgbWV0aG9kID0gInJmIiwgIyA4NSB3aXRoIHJwYXJ0MgogIHR1bmVMZW5ndGggPSA4LAogIHRyQ29udHJvbCA9IGZpdENvbnRyb2wsCiAgbWV0cmljID0gIlJPQyIKKQoKcHJlZCA8LSBwcmVkaWN0KHJmX2FsbF9vdXRsaWVyMiwgZGF0YVRlc3QpCnBvc3RSZXNhbXBsZShwcmVkID0gcHJlZCwgb2JzID0gZGF0YVRlc3Qkb3V0bGllcikKY29uZnVzaW9uTWF0cml4KGRhdGEgPSBwcmVkLCByZWZlcmVuY2UgPSBkYXRhVGVzdCRvdXRsaWVyLCBtb2RlID0gInNlbnNfc3BlYyIpCnByZWQgPC0gcHJlZGljdChyZl9hbGxfb3V0bGllcjIsIHRvdGVzdCkKcG9zdFJlc2FtcGxlKHByZWQgPSBwcmVkLCBvYnMgPSB0b3Rlc3Qkb3V0bGllcikKY29uZnVzaW9uTWF0cml4KGRhdGEgPSBwcmVkLCByZWZlcmVuY2UgPSB0b3Rlc3Qkb3V0bGllciwgbW9kZSA9ICJzZW5zX3NwZWMiKQoKCnByZWQgPC0gcHJlZGljdChyZl9hbGxfb3V0bGllcjIsIHRvdGVzdCwgdHlwZT0gInByb2IiKQpBVUMocHJlZCR5ZXMsIGlmZWxzZSh0b3Rlc3Qkb3V0bGllciA9PSAieWVzIiwgMSwgMCkpCgp2aXAocmZfYWxsX291dGxpZXIyKQpgYGAKCgojIEFob3JhIHBhcmEgbG9zIGN1YXJ0aWxlcwoKCmBgYHtyfQp0b3RyYWluIDwtIGRhdGFfcXVhcnRpbGVzX25vcm1hbGl6ZWQgJT4lIAogIGZpbHRlcihuIT0xMCkgJT4lCiAgc2VsZWN0KHN0YXJ0c193aXRoKCJtdSIpLCBxdWFydGlsZSkgJT4lCiAgbXV0YXRlKHF1YXJ0aWxlID0gZmN0X2NvbGxhcHNlKHF1YXJ0aWxlLCBmYXN0ID0gYygicTEiKSwgc2xvdyA9IGMoInEyIiwicTMiLCJxNCIpKSkKCnRvdGVzdCA8LSBkYXRhX3F1YXJ0aWxlc19ub3JtYWxpemVkICU+JSAKICBmaWx0ZXIobj09MTApICU+JQogIHNlbGVjdChzdGFydHNfd2l0aCgibXUiKSwgcXVhcnRpbGUpICU+JQogIG11dGF0ZShxdWFydGlsZSA9IGZjdF9jb2xsYXBzZShxdWFydGlsZSwgZmFzdCA9IGMoInExIiksIHNsb3cgPSBjKCJxMiIsInEzIiwicTQiKSkpCiAgCnNldC5zZWVkKDEyMykKdHJhaW5JbmRleCA8LSBjcmVhdGVEYXRhUGFydGl0aW9uKHRvdHJhaW4kcXVhcnRpbGUsIHAgPSAuOCwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBsaXN0ID0gRkFMU0UsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdGltZXMgPSAxKQoKZGF0YVRyYWluIDwtIHRvdHJhaW5bIHRyYWluSW5kZXgsXQpkYXRhVGVzdCAgPC0gdG90cmFpblstdHJhaW5JbmRleCxdCgpzZXQuc2VlZCgxMjMpCnJmX3F1YXJ0aWxlcyA8LSB0cmFpbigKICBxdWFydGlsZSB+LiwgZGF0YSA9IGRhdGFUcmFpbiwgbWV0aG9kID0gInJmIiwKICB0dW5lTGVuZ3RoID0gMTAsCiAgdHJDb250cm9sID0gZml0Q29udHJvbCwKICBtZXRyaWMgPSAiUk9DIgopIAoKcHJlZCA8LSBwcmVkaWN0KHJmX3F1YXJ0aWxlcywgZGF0YVRlc3QpCnBvc3RSZXNhbXBsZShwcmVkID0gcHJlZCwgb2JzID0gZGF0YVRlc3QkcXVhcnRpbGUpCiMgY29uZnVzaW9uTWF0cml4KGRhdGEgPSBwcmVkLCByZWZlcmVuY2UgPSBkYXRhVGVzdCRxdWFydGlsZSwgbW9kZSA9ICJzZW5zX3NwZWMiKQpwcmVkIDwtIHByZWRpY3QocmZfcXVhcnRpbGVzLCB0b3Rlc3QpCnBvc3RSZXNhbXBsZShwcmVkID0gcHJlZCwgb2JzID0gdG90ZXN0JHF1YXJ0aWxlKQpjb25mdXNpb25NYXRyaXgoZGF0YSA9IHByZWQsIHJlZmVyZW5jZSA9IHRvdGVzdCRxdWFydGlsZSwgbW9kZSA9ICJzZW5zX3NwZWMiKQoKcHJlZCA8LSBwcmVkaWN0KHJmX3F1YXJ0aWxlcywgdG90ZXN0LCB0eXBlPSAicHJvYiIpCkFVQyhwcmVkJGZhc3QsIGlmZWxzZSh0b3Rlc3QkcXVhcnRpbGUgPT0gImZhc3QiLCAxLCAwKSkKCnZpcChyZl9xdWFydGlsZXMpCmBgYAoKYGBge3J9CnRvdHJhaW4gPC0gZGF0YV9xdWFydGlsZXNfbm9ybWFsaXplZCAlPiUgCiAgZmlsdGVyKG4hPTEwKSAlPiUKICBzZWxlY3Qoc3RhcnRzX3dpdGgoIm11IiksIHF1YXJ0aWxlKSAlPiUKICBtdXRhdGUocXVhcnRpbGUgPSBmY3RfY29sbGFwc2UocXVhcnRpbGUsIGZhc3QgPSBjKCJxMSIpLCBzbG93ID0gYygicTIiLCJxMyIsInE0IikpKQoKdG90ZXN0IDwtIGRhdGFfcXVhcnRpbGVzX25vcm1hbGl6ZWQgJT4lIAogIGZpbHRlcihuPT0xMCkgJT4lCiAgc2VsZWN0KHN0YXJ0c193aXRoKCJtdSIpLCBxdWFydGlsZSkgJT4lCiAgbXV0YXRlKHF1YXJ0aWxlID0gZmN0X2NvbGxhcHNlKHF1YXJ0aWxlLCBmYXN0ID0gYygicTEiKSwgc2xvdyA9IGMoInEyIiwicTMiLCJxNCIpKSkKICAKc2V0LnNlZWQoMTIzKQp0cmFpbkluZGV4IDwtIGNyZWF0ZURhdGFQYXJ0aXRpb24odG90cmFpbiRxdWFydGlsZSwgcCA9IC44LCAKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGxpc3QgPSBGQUxTRSwgCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICB0aW1lcyA9IDEpCgpkYXRhVHJhaW4gPC0gdG90cmFpblsgdHJhaW5JbmRleCxdCmRhdGFUZXN0ICA8LSB0b3RyYWluWy10cmFpbkluZGV4LF0KCnNldC5zZWVkKDEyMykKcmZfcXVhcnRpbGVzMiA8LSB0cmFpbigKICBxdWFydGlsZSB+LiwgZGF0YSA9IGRhdGFUcmFpbiwgbWV0aG9kID0gInJwYXJ0MiIsCiAgdHVuZUxlbmd0aCA9IDEwLAogIHRyQ29udHJvbCA9IGZpdENvbnRyb2wsCiAgbWV0cmljID0gIlJPQyIKKSAKCnByZWQgPC0gcHJlZGljdChyZl9xdWFydGlsZXMyLCBkYXRhVGVzdCkKcG9zdFJlc2FtcGxlKHByZWQgPSBwcmVkLCBvYnMgPSBkYXRhVGVzdCRxdWFydGlsZSkKIyBjb25mdXNpb25NYXRyaXgoZGF0YSA9IHByZWQsIHJlZmVyZW5jZSA9IGRhdGFUZXN0JHF1YXJ0aWxlLCBtb2RlID0gInNlbnNfc3BlYyIpCnByZWQgPC0gcHJlZGljdChyZl9xdWFydGlsZXMyLCB0b3Rlc3QpCnBvc3RSZXNhbXBsZShwcmVkID0gcHJlZCwgb2JzID0gdG90ZXN0JHF1YXJ0aWxlKQpjb25mdXNpb25NYXRyaXgoZGF0YSA9IHByZWQsIHJlZmVyZW5jZSA9IHRvdGVzdCRxdWFydGlsZSwgbW9kZSA9ICJzZW5zX3NwZWMiKQoKcHJlZCA8LSBwcmVkaWN0KHJmX3F1YXJ0aWxlczIsIHRvdGVzdCwgdHlwZT0gInByb2IiKQpBVUMocHJlZCRmYXN0LCBpZmVsc2UodG90ZXN0JHF1YXJ0aWxlID09ICJmYXN0IiwgMSwgMCkpCgp2aXAocmZfcXVhcnRpbGVzMikKYGBgCgpgYGB7cn0KdmlwKHJmX3F1YXJ0aWxlczIsIAogICAgbnVtX2ZlYXR1cmVzID0gNSwKICAgIGFlc3RoZXRpY3MgPSBsaXN0KHdpZHRoID0gLjUpKSArCiAgdGhlbWVfYncoKSArIAogIHNjYWxlX3hfZGlzY3JldGUobGFiZWxzID0gZnVuY3Rpb24oeCkgcGFyc2UodGV4dD1wYXN0ZTAoIm11WyIsIHN0cl9yZW1vdmUoeCwgIm11IiksICJdIikpKSArCiAgeWxhYigiVmFyaWFibGUgaW1wb3J0YW5jZSIpICsKICB0aGVtZSh0ZXh0PWVsZW1lbnRfdGV4dChzaXplID0gMTIsIGZhbWlseT0iVGltZXMgTmV3IFJvbWFuIiksCiAgICAgICAgYXhpcy50aXRsZS54ID0gZWxlbWVudF90ZXh0KG1hcmdpbiA9IG1hcmdpbih0ID0gMTApKSkKYGBgCgo=